/*
 * Copyright (c) 2020, yifengling0. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. No personal names or organizations' names associated with the
 *    Atomthreads project may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>

#include "atom.h"
#include "debug.h"
#include "console.h"
#include <string.h>
#include "iosdrv.h"
#include "spi.h"
#include "simSpi.h"
#include "pin.h"
#include "a7139.h"
#include "syslog.h"
#include "rtc.h"
#include "numberical.h"
#include "eventmgr.h"
#include "packet.h"
#include "hw.h"

#ifdef COM_USE_CONSOLE  

static enConsoleResult spitest(int argc, char** argv)
{
    FD fd = open("simSpi", 0, 0);

    write(fd, "hello world", 11);
    
    return CE_OK;
}

static void a7139_Init(void)
{
    KPrint("init a7139..");
    A7139_Init(433.921f, PKG_A7139_CID);
    KPrint("OK\r\n");
    Uint16 pid = A7139_ReadPID();
    KPrintValue(" read pid :", pid, 16, 0, 1);
}

static void a7139_getrssi(void)
{
    uint8_t ver = A7139_GetRSSI();
    KPrintValue(" read rssi :", ver, 10, 0, 1);
}

static void a7139_readcid(void)
{
    uint32_t cid = A7139_ReadCID();
    KPrintf(" read cid :%08x\r\n", cid);
}

static void a7139_send(uint8_t* data, uint8_t len)
{
    SYSLOG(LOG_INFO, "sending...");
    A7139_fifoSend(data, len);
    SYSLOG(LOG_INFO, "end");
}

static void a7139_mode( uint8_t mode)
{
    SYSLOG(LOG_INFO, "mode %02X changing...", (uint32_t)mode);
    A7139_GotoMode(mode);
    SYSLOG(LOG_INFO, "end");
}

static void a7139_recv(void)
{
    Uint8 tmpbuf[64];
    
    while(1) {
        if (DebugPortIsReadable()) {
           char c = DebugPortGetChar();
           if(c=='q'){
                break;
            }
        }
        if( !A7139_isBusy() ){
            A7139_fifoRead(tmpbuf);
            KDumpPrint(tmpbuf, 64);
            break;
        }
        else{
            atomTimerDelay(2);
        }
    }
}


static void a7139_send_proc(int argc, char** argv)
{
    if( strcmp(argv[2], "sync") == 0){
        if( argc == 9){
            uint16_t year;
            uint8_t month, day, hour, min, sec;
            year = StringToInt(argv[3]);
            month = StringToInt(argv[4]);
            day = StringToInt(argv[5]);
            hour = StringToInt(argv[6]);
            min = StringToInt(argv[7]);
            sec = StringToInt(argv[8]);
            PacketSyncRtc show;
            MakeSyncRtcPacket(&show, year, month, day, hour, min, sec);
            a7139_send((uint8_t*)&show, sizeof(PacketSyncRtc));
        }
    }else if( strcmp(argv[2], "rtc") == 0){
        if( argc == 4){
            int index = StringToInt(argv[3]);
            PacketShowRtc show;
            MakeShowRtcPacket(&show, index);
            a7139_send((uint8_t*)&show, sizeof(PacketShowRtc));
        }
    }else if( strcmp(argv[2], "pic") == 0){
        if( argc == 4){
            int index = StringToInt(argv[3]);
            PacketShowPic show;
            MakeShowPicPacket(&show, index);
            a7139_send((uint8_t*)&show, sizeof(PacketShowPic));
        }
    }
}

static enConsoleResult a7139_proc(int argc, char** argv)
{
    if(argc < 2){
        KPrint("usage: a7139 [init|rssi|cid|send|recv|mode] param1 param2 ...\r\n");
        return CE_OK;
    }else{
        if( strcmp(argv[1], "init") == 0){
            a7139_Init();
        }else if( strcmp(argv[1], "rssi") == 0){
            a7139_getrssi();
        }else if( strcmp(argv[1], "readcid") == 0){
            a7139_readcid();
        }else if( strcmp(argv[1], "setcid") == 0){
            uint32_t cid = HexStringToInt(argv[2]);
            A7139_SetCID(cid);
            KPrintValue("set cid :", cid, 16, 8, 1);
        }else if( strcmp(argv[1], "send") == 0){
            if( argc < 3){
                KPrint("usage: a7139 send sync|rtc|pic yyyy mm dd hh mm ss|index|index\r\n");
            }else{
                a7139_send_proc(argc, argv);
            }
        }else if( strcmp(argv[1], "recv") == 0){
            a7139_recv();
        }else if( strcmp(argv[1], "mode") == 0){
            uint8_t mode = HexStringToInt(argv[2]);
            a7139_mode(mode);
        }else if( strcmp(argv[1], "worsync") == 0){
            uint32_t ret = A7139_WOR_BySync();
            SYSLOG(LOG_INFO, "result:%d", ret);
        }else if( strcmp(argv[1], "worPreamble") == 0){
            uint32_t ret = A7139_WOR_ByPreamble();
            SYSLOG(LOG_INFO, "result:%d", ret);
        }else if( strcmp(argv[1], "wot") == 0){
            uint32_t ret = A7139_WOT();
            SYSLOG(LOG_INFO, "result:%d", ret);
        }else{
            SYSLOG(LOG_WARNING, "error command");
        }
    }

    return CE_OK;
}

static int isKeyPress(char key)
{
    if (DebugPortIsReadable()) {
        char c = DebugPortGetChar();
        if(c=='q'){
            return 1;
        }
    }

    return 0;
}

void lprtc_cb(RtcWakeUp *wakeup)
{
    event_mgr_set(EVENT_RTC_WAKEUP, 5);
}

static enConsoleResult lprtc(int argc, char** argv)
{
    ATOM_EX_EVENT event;
    RtcWakeUp wakeup = { 1, RTCCLK_Div16, 2048*5, lprtc_cb };

    KPrint("\r\n");
    KPrint("low power rtc test (5 sec), press q to exit!\r\n");
    event_mgr_init();
    RtcSetWakeUp(&wakeup);

    while(1){
        uint8_t result = event_mgr_wait(&event, 100);
        if(result == ATOM_OK && event.type == EVENT_RTC_WAKEUP){
            int year, month, day, hour, minute, second;
            RtcGetDatetime(&year, &month, &day, &hour, &minute, &second);
            KPrintf("\r%d/%02d/%02d %02d:%02d:%02d", (uint32_t)year, (uint32_t)month, 
                    (uint32_t)day, (uint32_t)hour, (uint32_t)minute, (uint32_t)second);
            
            if( isKeyPress('q') ){
                wakeup.enable = 0;
                RtcSetWakeUp(&wakeup);
                break;
            }else{
                atomTimerDelay(10);
                halt();
            }
        }
    }

    return CE_OK;
}

#endif

BGEIN_DEF_CMD(_appCmds)
    CMD_DEF(spitest, "test sim spi ")
    CMD_DEF_ALISA(a7139, a7139_proc, "a7139 [init|rssi|readcid|setcid|send|recv|mode] param1 param2 ...")
    CMD_DEF(lprtc, "show time clock")
END_DEF_CMD()

void AppCmdInit()
{
	CONSOLE_REG_CMD(_appCmds);
}